package com.qyl.framework.handler;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Maps;
import com.qyl.framework.base.protocol.RequestProto;
import com.qyl.framework.base.protocol.ResponseProto;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * 
 * @author created by 齐翌来（qiyilai@foxmail.com）
 * 
 * 2019年2月17日
 * 
 * @description
 * 执行rpc逻辑
 */
public class InvokeHandler extends ChannelInboundHandlerAdapter  {
	
	private static final Logger logger = LoggerFactory.getLogger(InvokeHandler.class);
	
	private ConcurrentMap<String, Object> class2ServiceMap = Maps.<String, Object>newConcurrentMap();
	
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		
		logger.info("InvokeHandler channelRead");
		
		RequestProto requetProto = RequestProto.class.cast(msg);
		String className = requetProto.getClassName();
		Object serviceObject = class2ServiceMap.get(className);
		if (serviceObject == null) {
			serviceObject = Class.forName(className).newInstance();
			Object oldObject = class2ServiceMap.putIfAbsent(className, serviceObject);
			if (oldObject != null) {
				serviceObject = oldObject;
			}
		}
		Method method = null;
		if (requetProto.getParamClasses() == null) {
			method = serviceObject.getClass().getMethod(requetProto.getMethodName());
		} else {
			method = serviceObject.getClass().getMethod(requetProto.getMethodName(), requetProto.getParamClasses());
		}
		Object result = null;
		if (requetProto.getParamValues() == null) {
			result = method.invoke(serviceObject);
		} else {
			result = method.invoke(serviceObject, requetProto.getParamValues());
		}
		logger.info("InvokeHandler get result = {}", result.toString());
		ResponseProto responseProto = new ResponseProto(requetProto.getRequestId(), result);
		ctx.channel().writeAndFlush(responseProto);
	}
	
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		super.channelReadComplete(ctx);
	}
}
